#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <cassert>
#include <functional>
#include  <pthread.h>
using namespace std;


// 上下文类 作为线程启动时的参数传递载体
class Context 
{
    public:
        Thread *_this;  // 保存Thread对象的this指针 用于访问成员函数
        void *_args;    // 保存用户传入的参数 将传递给线程函数
        
    public:
        Context() : _this(nullptr), _args(nullptr) {}
        ~Context() {}
};


class Thread
{
    public:
    // 定义线程函数类型 返回void* 参数为void*
    using func_t=function<void*(void*)>;
    const int num=1024;
    public:
    Thread(func_t func,void* args=nullptr,int number=0) :_func(func),_args(args)
    {
        char buffer[num];
        snprintf(buffer,sizeof(buffer),"thread-%d",number);
        _name=buffer;

        //创建并初始化上下文
        Context *ctx = new Context();
        ctx->_this = this; //保存当前对象指针
        ctx->_args = _args; //保存用户参数
        //创建线程
        int n = pthread_create(&_tid, nullptr, start_routine, ctx);
        assert(n == 0); 
        (void)n;
        //assert在编译debug的方式发布的时候存在
        //在release方式发布 assert就不存在了
        //n就是一个定义但未被使用的变量
        //在有些编译器下会有warning
        //所以把n强转成void 防止编译器报错
        
    }


    // 在类内创建线程 想让线程执行对应的方法 需要将方法设置成为static
    static void *start_routine(void *args) //类内成员 有缺省参数！
    {
            // 获取上下文
            Context *ctx = static_cast<Context*>(args);   
            // 通过上下文调用真正的线程执行函数
            void *ret = ctx->_this->run(ctx->_args);            
            // 释放上下文资源
            delete ctx;
            return ret;
    }

    void join()
    {
        int n = pthread_join(_tid, nullptr);
        assert(n == 0);
        (void)n;
    }

    void *run(void *args)
    {
        return _func(args);
    }

    ~Thread() 
    {
        if (pthread_join(_tid, nullptr) != 0) 
        {
            // 线程可能已经detached或已经joined
            pthread_detach(_tid);
        }
    }

private:
    string _name;
    func_t _func;
    void* _args;
    pthread_t _tid;

};


